#pragma once

#include "types.h"
#include "fighting.hpp"
#include "lines.hpp"
#include "mockif.hpp"
#include "spacetime.hpp"
#include "wave.hpp"
#include "wfw.hpp"
#include <cstdint>

namespace Trade {

#define TO_MINUTES(tm) ((tm) ? (int((tm)-t_now_) / 60) : 0)


enum class PET_STATUS : uint32_t {
  NONE,
  NORMAL,
  OPENED,
  REDUCE_POSITION,
  CLOSE_MIN_WIN,
};

struct Schrodinger
{
protected:
  dir_t dir = 0;

public:
  bool outed = false; // timer outed1
  bool waiting_for_line2 = false;
  case_t case_no = 0;
  int whoami = 0;
  int amout_to = 0;
  int amount_rl2 = 0;
  int64_t my_idx = 0;
  time_t my_tm = 0;
  price_t my_hp = 0;
  price_t reached_line = 0;
  MockIF* mock = nullptr;
  price_t os_entries = 0;
  PET_STATUS status = PET_STATUS::NONE;

  Spacetime target;
  Incomming incomming;
  Lines prev_lines;
  Pricing open;
  Pricing close;


public:
  dir_t get_dir() const noexcept { return (dir) ? dir : 0; }
  bool is_running() const noexcept { return (dir != 0); }

  void print(const char* title,
             const int64_t idx,
             const price_t hp_now,
             const time_t t_now) noexcept;
  bool set_timer(const time_t tm, const time_t tm2) noexcept;
  bool update_lines(const Lines& l, const price_t hp_now) noexcept;
  Timer* get_timer() noexcept;
  Lines& get_limits_lines() noexcept;
  Spacetime* get_target() noexcept;

  uint8_t check_reached(const time_t t_now,
                        const price_t hp_now,
                        Lines& l_now,
                        const int64_t idx) noexcept;

  dir_t opposite() noexcept { return (-dir); }
  uint8_t reacheded() const noexcept;
  void clear_reacheded() noexcept;
  bool reached_line2() noexcept;
  bool reached_line1() noexcept;
  bool reached_oppo_line2() noexcept;
  bool reached_oppo_line1() noexcept;
  bool timer_outed() noexcept;
  bool current_timer_outed() noexcept;
  void update_timer(const time_t tm, const time_t tm2) noexcept;
  void erase_opposite_reached(const uint8_t rchd) noexcept;

  void set_timer_outed() noexcept { outed = true; }
  bool d5_was_reversed(const Dir5& d5) noexcept;
  void update_g2(const WaitingForWrong& wfw, const Wave& wave) noexcept;
  bool should_renew_lines(const Lines& l,
                          const time_t t_now,
                          const price_t hp_now) noexcept;
  void renew_target(const Lines& lines,
                    const time_t tm,
                    const time_t t_now,
                    const price_t hp_now,
                    const int64_t idx) noexcept;
#if (ONLINE_DATA_COMM)
  int get_json(char* buf, const int buf_len, const char* name);
#endif // ONLINE_DATA_COMM

  ~Schrodinger()
  {
    // if (dc)
    //  delete dc;
  }

  void set_mock_nterface(MockIF* mockif) noexcept { mock = mockif; }

  void run(const dir_t d,
           const time_t tm,
           const time_t tm2,
           const Lines& lines,
           const price_t hp_now,
           const time_t t_now,
           const int64_t idx,
           const case_t cno,
           const int whoami) noexcept;
  void stop(const int64_t idx, const int64_t tm, const uint32_t cno) noexcept;

  price_t get_revenue() const noexcept { return incomming.rvn_single; }
  uint8_t reached(const time_t t_now,
                  const price_t hp_now,
                  Lines& l_now,
                  const int64_t idx) noexcept;
  void reset() noexcept;
  void copy_from(const Schrodinger* sdg) noexcept;
  void print_revenue(const price_t hp_now, const time_t t_now) const noexcept;

  void print(const char* title,
             const int64_t idx,
             const price_t hp_now,
             const time_t t_now) const noexcept;

  bool second_timer_outed(const time_t t_now) noexcept;
  int get_durantion(const time_t t_now) noexcept;
  void renew_lines(const dir_t d, const Lines& ls, const price_t hp_now) noexcept;
  void reached_additional_line2(const dir_t d, const price_t hpx) noexcept;
  
};

} // namespace Trade
